home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / umddvi / lib / rotate.c < prev    next >
C/C++ Source or Header  |  1990-10-01  |  3KB  |  151 lines

  1. /*
  2.  * Copyright (c) 1987 University of Maryland Department of Computer Science.
  3.  * All rights reserved.  Permission to copy for any purpose is hereby granted
  4.  * so long as this copyright notice remains intact.
  5.  */
  6.  
  7. #ifndef lint
  8. static char rcsid[] = "$Header: rotate.c,v 2.3 87/06/16 18:28:45 chris Exp $";
  9. #endif
  10.  
  11. /*
  12.  * Routines to generate rotated bitmaps given unrotated inputs.
  13.  *
  14.  * The rotated bitmap is indistinguishable from the unrotated one (aside
  15.  * from being rotated of course!).
  16.  */
  17.  
  18. #include "font.h"
  19.  
  20. extern    int errno;
  21.  
  22. char    *malloc();
  23.  
  24. /*
  25.  * Rounding, but by powers of two only.
  26.  */
  27. #define ROUND(n,r) (((n) + ((r) - 1)) & ~((r) - 1))
  28.  
  29. /*
  30.  * Set the rotation of glyph g to r.
  31.  */
  32. SetRotation(g, r)
  33.     register struct glyph *g;
  34.     int r;
  35. {
  36.  
  37.     if (r < ROT_NORM || r > ROT_RIGHT)
  38.         error(1, 0, "bad rotation value %d", r);
  39.  
  40.     /*
  41.      * The null glyph is trivial to rotate by any amount.
  42.      *
  43.      * Note that this assumes that any raster has been obtained
  44.      * BEFORE calling SetRotation()!
  45.      */
  46.     if (g->g_raster == NULL) {
  47.         g->g_rotation = r;
  48.         return;
  49.     }
  50.  
  51.     /*
  52.      * This is hardly efficient, but it *is* expedient....
  53.      */
  54.     while (g->g_rotation != r) {
  55.         RotateClockwise(g);
  56.         g->g_rotation = (g->g_rotation - 1) & 3;
  57.     }
  58. }
  59.  
  60. /*
  61.  * Rotation by 1/4 turn clockwise (from ROT_NORM to ROT_RIGHT, e.g.).
  62.  */
  63. static
  64. RotateClockwise(glyph)
  65.     struct glyph *glyph;
  66. {
  67.     register char *nrast;    /* new raster */
  68.     register char *orast;    /* old raster */
  69.     register int oheight;    /* old raster height, new raster width */
  70.     register int owidth;    /* old raster width, new raster height */
  71.     unsigned int size;    /* size of new raster (in bytes) */
  72.     int nplus;        /* offset between rows in nrast */
  73.  
  74.     /*
  75.      * First, get a new raster.
  76.      */
  77.     {
  78.         register struct glyph *g = glyph;
  79.         register int t;
  80.  
  81.         oheight = g->g_height;
  82.         owidth = g->g_width;
  83.  
  84.         /*
  85.          * Offset is (new width) rounded to bytes.
  86.          */
  87.         nplus = ROUND(oheight, 8) >> 3;
  88.  
  89.         /*
  90.          * Size of new raster is (new height) * (new rounded width,
  91.          * in bytes).
  92.          */
  93.         size = nplus * owidth;
  94.         if ((nrast = malloc(size)) == NULL)
  95.             error(1, errno, "out of memory");
  96.         bzero(nrast, size);
  97.  
  98.         /*
  99.          * New y origin is old x origin; new x origin is old height
  100.          * minus old y origin - 1.
  101.          */
  102.         t = g->g_yorigin;
  103.         g->g_yorigin = g->g_xorigin;
  104.         g->g_xorigin = oheight - t - 1;
  105.  
  106.         /* While we are at it, exchange height & width... */
  107.         g->g_height = owidth;
  108.         g->g_width = oheight;
  109.  
  110.         /* and grab a pointer to the old raster. */
  111.         orast = g->g_raster;
  112.     }
  113.  
  114.     /*
  115.      * Now copy bits from the old raster to the new one.  The mapping
  116.      * function is
  117.      *
  118.      *    for i in [0..height)
  119.      *        for j in [0..width)
  120.      *            new[j, height-i-1] = old[i, j] 
  121.      *
  122.      * Thus i maps to height-i-1 and (since we have to do our own 2
  123.      * dimensional array indexing) j to nplus*j.  We call the mapped
  124.      * variables mapi and mapj, and, since we scan sequentially through
  125.      * the old raster, can discard the original i and j.
  126.      */
  127.     {
  128.         register int mapj, c, k, mapi;
  129.  
  130.         mapi = oheight;
  131.         owidth *= nplus;
  132.         while (--mapi >= 0) {
  133.             k = 7;
  134.             for (mapj = 0; mapj < owidth; mapj += nplus) {
  135.                 if (++k == 8)    /* get another byte */
  136.                     c = *orast++, k = 0;
  137.                 if (c & 0x80)    /* old[i,j] was set */
  138.                     nrast[mapj + (mapi >> 3)] |=
  139.                         1 << (7 - (mapi & 7));
  140.                 c <<= 1;
  141.             }
  142.         }
  143.     }
  144.  
  145.     /*
  146.      * Finally, free the storage associated with the original raster.
  147.      */
  148.     free(glyph->g_raster);
  149.     glyph->g_raster = nrast;
  150. }
  151.